package com.leilei.controller;

import com.leilei.model.*;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.IOException;
import java.util.concurrent.ConcurrentLinkedQueue;


/**
 * Created by zl206 on 2016/11/15.
 */
public class Play {
    private static ObjectMapper objectMapper=new ObjectMapper();
    public static String GetData(ConcurrentLinkedQueue<Effect> effects) throws IOException {
        String bullets = objectMapper.writeValueAsString(Game.bullets);
        String walls = objectMapper.writeValueAsString(Game.walls);
        String map = objectMapper.writeValueAsString(Game.map);
        String health = objectMapper.writeValueAsString(Game.HealthPlaces);
        String power = objectMapper.writeValueAsString(Game.PowerPlaces);
        String effect=objectMapper.writeValueAsString(effects.poll());
        return "{\"code\":1,\"content\":{\"b\":"+bullets+",\"w\":"+walls+",\"m\":"+map+",\"h\":"+health+",\"p\":"+power+",\"e\":"+effect+"}}";
    }
    public static void bulletGo(Bullet bullet){
        new Thread(()->{
            while (
                    bullet.getPoint().getX()>0&&
                            bullet.getPoint().getX()<1000&&
                            bullet.getPoint().getY()>0&&
                            bullet.getPoint().getY()<1000
                    ){
                Tool.forward(bullet.getPoint(),10,bullet.getFace());
                BulletFight(bullet);
                try {
                    Thread.sleep(1000/30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Game.bullets.remove(bullet);
        }).start();
    }
    public static void  BulletFight(Bullet bullet){

    }


    //------------------------------------------------------------------------------------------------------------------
    public static void WallGo(Wall wall){
        new Thread(()->{
            while (
                    Game.walls.contains(wall)&&
                    wall.getPoint().getX()>0&&
                    wall.getPoint().getX()<1000&&
                    wall.getPoint().getY()>0&&
                    wall.getPoint().getY()<1000
                    ){
                Tool.forward(wall.getPoint(),(wall.getBlood()/3+1),wall.getFace());
                WallFight(wall);
                try {
                    Thread.sleep(1000/60);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Game.walls.remove(wall);
        }).start();
    }

    public static void WallGrow(Player player, MyBigBullet myBigBullet){
        Wall wall=myBigBullet.getMyWall();
        new Thread(()->{
            while (Game.walls.contains(wall)&&myBigBullet.isGrow()){
                if (myBigBullet.getPower().get()>0){
                    wall.recoveryBlood();
                    myBigBullet.getPower().decrementAndGet();
                    wall.setPoint(Tool.forwardP(player.getPoint(),20+wall.getBlood()+10+1,wall.getFace()));
                }else{
                    myBigBullet.setGrow(false);
                }
                WallFight(wall);
                try {
                    Thread.sleep(1000/30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Play.WallGo(wall);
        }).start();
    }


    public static void WallFight(Wall wall){
        WallFightWall(wall);
        WallFightBullets(wall);
    }

    public static void WallFightWall(Wall wall){
        int size=Game.walls.size();
        if(size>1){
            Wall[] walls = new Wall[size];
            Wall[] ws=Game.walls.toArray(walls);
            for(Wall wall1:ws){
                if (wall.equals(wall1)||wall1.getPoint()==null)continue;
                double len=Tool.getL(wall.getPoint(),wall1.getPoint());
                double L=wall.getBlood()+wall1.getBlood()+20;
                int Lblood=2*(wall.getBlood()>wall1.getBlood()?wall1.getBlood():wall.getBlood());
                double LL=L-len;
                double LLL=Lblood>LL?LL:Lblood;
                if(LLL>2){
                    wall.dropBlood((int) (LL/2));
                    wall1.dropBlood((int) (LL/2));
                }else if(LLL>0){
                    wall.dropBlood();
                    wall1.dropBlood();
                }
            }
        }
    }



    public static void WallFightBullets(Wall wall){
        Game.bullets.forEach(e->{
            if(Tool.isClose(e.getPoint(),wall.getPoint(),wall.getBlood()+10)){
                wall.dropBlood();
                Game.bullets.remove(e);
            }
        });
    }
    //----------------------------------------------------------------------
    public static Player PlayerFight(Player player,MyBigBullet myBigBullet){
        PlayerFightBullet(player,myBigBullet);
        PlayerFightWall(player,myBigBullet);
        return player;
    }

    public static void PlayerFightBullet(Player player,MyBigBullet myBigBullet){
        Game.bullets.forEach(e->{
            if(myBigBullet.getHealth().get()>0)
                if(Tool.isClose(player.getPoint(),e.getPoint(),20)){
                    if(myBigBullet.dropHealth(e.getPlayer()))
                        try {
                            Game.effects.put(new Effect(player.getPoint(),1));
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                    Game.bullets.remove(e);
                }
        });
    }

    public static void PlayerFightWall(Player player,MyBigBullet myBigBullet){
        final int DB=10;
        Game.walls.forEach(e->{
            if(e.getBlood()>0) {
                double L=Tool.getL(player.getPoint(), e.getPoint());
                double LL=(e.getBlood() + 30-L);
                double LLL=min(LL/DB,e.getBlood()/DB,myBigBullet.getHealth().get());
                if(LLL>0&&myBigBullet.dropHealth((int) LLL,e.getPlayer())){
                    try {
                        Game.effects.put(new Effect(player.getPoint(),1));
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    e.dropBlood((int) LLL*DB);
                }else if(LL>0&&myBigBullet.dropHealth(e.getPlayer())){
                    try {
                        Game.effects.put(new Effect(player.getPoint(),1));
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    Game.walls.remove(e);
                }
            }else {
                Game.walls.remove(e);
            }
        });
    }

    //-----------------------------------------------------------------------
    public static void RecoveryHealth(Player player,MyBigBullet myBigBullet){
        Game.HealthPlaces.forEach(e->{
            if(Tool.isClose(e.getPoint(),player.getPoint(),e.getHealth().get()+50)){
                if(myBigBullet.getHealth().get()<10&&e.dropHealth()){
                    myBigBullet.getHealth().incrementAndGet();
                }
            }
        });
    }

    public static void RecoveryPower(Player player,MyBigBullet myBigBullet){
        Game.PowerPlaces.forEach(e->{
            if(Tool.isClose(e.getPoint(),player.getPoint(),e.getHealth().get()+50)){
                if(myBigBullet.getPower().get()<100){
                    new Thread(()->{
                        int time=300;
                        while (time>0){
                            if(myBigBullet.getPower().get()<100&&e.dropHealth()){
                                myBigBullet.getPower().incrementAndGet();
                            }
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e1) {
                                e1.printStackTrace();
                            }
                            time-=100;
                        }
                    }).start();
                }
            }
        });
    }
    public static double min(double... doubles){
        if (doubles.length==0) try {
            throw  new Exception("参数不正确");
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
        double min=doubles[0];
        if (doubles.length==1)return min;
        for (int i =1 ; i< doubles.length;++i){
            min=Math.min(min,doubles[i]);
        }
        return min;
    }
}
